package com.abc.xxx.config.security;

import com.abc.xxx.config.Settings;
import com.abc.xxx.service.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.servlet.Filter;

@Slf4j
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private Settings settings;
    @Autowired
    private RoleService roleService;

    @Bean
    public UserDetailsService userDetailsService(){
        return new UserDetailsServiceImpl();
    }

    @Bean
    public JwtService jwtService(){
        return new JwtService(
                settings.getJwtSecret(),
                settings.getJwtExpire(),
                settings.getJwtAutoRefreshInAdvance());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //super.configure(auth);
        auth.userDetailsService(userDetailsService());
    }

    @Bean
    public Filter loginFilter() throws Exception {
        LoginFilter filter = new LoginFilter(jwtService(),roleService);
        //这句很关键，重用WebSecurityConfigurerAdapter配置的AuthenticationManager，不然要自己组装AuthenticationManager
        filter.setAuthenticationManager(authenticationManager());
        return filter;
    }

    @Bean
    public Filter jwtFilter() throws Exception {
        JwtFilter filter = new JwtFilter(jwtService(),settings.jwtWhiteList);
        return filter;
    }

    // 登录拦截相关配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)

                .and().authorizeRequests()
                .antMatchers(settings.jwtWhiteList.toArray(new String[0])).permitAll()
                .anyRequest().authenticated()

                .and().exceptionHandling()
                .accessDeniedHandler(new RestAccessDeniedHandler())
                .authenticationEntryPoint(new RestAuthenticationEntryPoint())

                .and().logout().logoutUrl("/auth/logout").logoutSuccessHandler(new RestLogoutSuccessHandler())

                .and()
                // 登录
                .addFilter(loginFilter())
                // 验证token
                .addFilterAfter(jwtFilter(), LoginFilter.class);

    }


}
